"""
Boss智能招聘助手主类
集成LangChain Agent、工具和记忆系统
"""
import os
import logging
from typing import Dict, Any, List, Optional
from langchain.agents import AgentExecutor, create_react_agent
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate

from .tools import get_all_tools
from .memory import RedisMemory
from .prompts import SYSTEM_PROMPT, REACT_PROMPT_TEMPLATE

logger = logging.getLogger(__name__)


class BossAgent:
    """
    Boss智能招聘助手
    
    核心功能：
    1. 自动选择合适的工具完成任务
    2. 多步骤任务规划与执行
    3. 会话记忆管理
    4. 统一错误处理
    
    示例：
        agent = BossAgent()
        result = agent.chat(
            user_input="帮我筛选Python工程师",
            user_id=123,
            session_id="sess_001"
        )
    """
    
    def __init__(
        self,
        model_name: str = "qwen-plus",
        temperature: float = 0.3,
        max_iterations: int = 10,
        verbose: bool = True
    ):
        """
        初始化Boss Agent
        
        Args:
            model_name: LLM模型名称，默认qwen-plus
            temperature: 生成温度（0-1），越低越确定
            max_iterations: 最大工具调用次数，防止死循环
            verbose: 是否打印详细日志
        """
        logger.info("=" * 60)
        logger.info("初始化Boss Agent...")
        logger.info("=" * 60)
        
        # 1. 初始化LLM
        self.llm = self._init_llm(model_name, temperature)
        logger.info(f"✅ LLM初始化成功: {model_name}")
        
        # 2. 加载所有工具
        self.tools = self._load_tools()
        logger.info(f"✅ 工具加载成功: {len(self.tools)}个工具")
        
        # 3. 初始化记忆系统
        self.memory = self._init_memory()
        logger.info("✅ 记忆系统初始化成功")
        
        # 4. 创建Agent
        self.agent = self._create_agent()
        logger.info("✅ Agent创建成功")
        
        # 5. 创建Executor
        self.executor = AgentExecutor(
            agent=self.agent,
            tools=self.tools,
            max_iterations=max_iterations,
            verbose=verbose,
            handle_parsing_errors=True,
            return_intermediate_steps=True  # 返回工具调用过程
        )
        logger.info("✅ AgentExecutor创建成功")
        logger.info("=" * 60)
        logger.info("Boss Agent初始化完成！")
        logger.info("=" * 60)
    
    def _init_llm(self, model_name: str, temperature: float) -> ChatOpenAI:
        """
        初始化大语言模型
        
        使用通义千问的OpenAI兼容接口
        """
        api_key = os.getenv("DASHSCOPE_API_KEY")
        
        if not api_key:
            raise ValueError(
                "DASHSCOPE_API_KEY环境变量未设置！\n"
                "请在环境变量中设置：export DASHSCOPE_API_KEY=your_api_key"
            )
        
        return ChatOpenAI(
            model=model_name,
            temperature=temperature,
            openai_api_key=api_key,
            openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",
            max_tokens=2000
        )
    
    def _load_tools(self) -> List:
        """
        加载所有工具
        
        Returns:
            工具列表（10个工具）
        """
        tools = get_all_tools()
        
        # 打印工具列表
        logger.info("\n📦 已加载工具:")
        for i, tool in enumerate(tools, 1):
            logger.info(f"  {i}. {tool.name} - {tool.description.split('.')[0]}")
        
        return tools
    
    def _init_memory(self) -> RedisMemory:
        """
        初始化记忆系统
        
        Returns:
            Redis记忆实例
        """
        return RedisMemory()
    
    def _create_agent(self):
        """
        创建ReAct Agent
        
        使用LangChain的create_react_agent创建Agent
        """
        # 构建Prompt
        prompt = PromptTemplate(
            template=REACT_PROMPT_TEMPLATE,
            input_variables=["input", "agent_scratchpad"],
            partial_variables={
                "tools": "\n".join([f"{tool.name}: {tool.description}" for tool in self.tools]),
                "tool_names": ", ".join([tool.name for tool in self.tools])
            }
        )
        
        return create_react_agent(
            llm=self.llm,
            tools=self.tools,
            prompt=prompt
        )
    
    def chat(
        self,
        user_input: str,
        user_id: int,
        session_id: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        对话入口（核心方法）
        
        Args:
            user_input: 用户输入
            user_id: 用户ID
            session_id: 会话ID（可选，不传则创建新会话）
        
        Returns:
            {
                "success": True/False,
                "output": "Agent回复内容",
                "intermediate_steps": [...],  # 工具调用过程
                "session_id": "sess_xxx",
                "tool_calls": 3  # 调用了几个工具
            }
        """
        import uuid
        
        # 生成session_id
        if not session_id:
            session_id = f"sess_{uuid.uuid4().hex[:12]}"
        
        logger.info("\n" + "=" * 60)
        logger.info(f"💬 新对话请求")
        logger.info(f"   User ID: {user_id}")
        logger.info(f"   Session ID: {session_id}")
        logger.info(f"   Input: {user_input[:100]}")
        logger.info("=" * 60)
        
        try:
            # 1. 加载历史对话
            history = self.memory.load(user_id, session_id)
            logger.info(f"📚 加载历史: {len(history)}条消息")
            
            # 2. 构建输入（包含系统prompt和历史）
            full_input = self._build_full_input(user_input, history)
            
            # 3. 执行Agent
            logger.info("🤖 Agent开始思考...")
            result = self.executor.invoke({
                "input": full_input
            })
            
            output = result.get('output', '')
            intermediate_steps = result.get('intermediate_steps', [])
            
            logger.info(f"✅ Agent执行完成: 调用了{len(intermediate_steps)}个工具")
            logger.info(f"   Output: {output[:100]}")
            
            # 4. 保存对话
            self.memory.save(
                user_id=user_id,
                session_id=session_id,
                user_input=user_input,
                agent_output=output,
                metadata={
                    "tool_calls": len(intermediate_steps),
                    "tools_used": [step[0].tool for step in intermediate_steps] if intermediate_steps else []
                }
            )
            
            # 5. 返回结果
            return {
                "success": True,
                "output": output,
                "intermediate_steps": intermediate_steps,
                "session_id": session_id,
                "tool_calls": len(intermediate_steps)
            }
            
        except Exception as e:
            logger.error(f"❌ Agent执行失败: {str(e)}", exc_info=True)
            return {
                "success": False,
                "error": str(e),
                "message": "抱歉，处理失败。可能的原因：\n"
                          "1. 工具调用超时\n"
                          "2. LLM服务不可用\n"
                          "3. 数据库连接失败\n"
                          "请稍后重试或联系技术支持。",
                "session_id": session_id
            }
    
    def _build_full_input(self, user_input: str, history: List[Dict]) -> str:
        """
        构建完整输入（包含系统prompt和历史）
        
        Args:
            user_input: 当前用户输入
            history: 历史对话
        
        Returns:
            完整的输入文本
        """
        # 添加系统prompt
        full_input = f"{SYSTEM_PROMPT}\n\n"
        
        # 添加历史对话（最近3轮）
        if history:
            recent_history = history[-6:]  # 最近3轮=6条消息
            full_input += "历史对话:\n"
            for msg in recent_history:
                role = "用户" if msg["role"] == "user" else "助手"
                full_input += f"{role}: {msg['content']}\n"
            full_input += "\n"
        
        # 添加当前输入
        full_input += f"当前问题: {user_input}"
        
        return full_input
    
    def clear_memory(self, user_id: int, session_id: str) -> bool:
        """
        清除会话记忆
        
        Args:
            user_id: 用户ID
            session_id: 会话ID
        
        Returns:
            是否成功
        """
        return self.memory.clear(user_id, session_id)
    
    def get_tool_list(self) -> List[Dict[str, str]]:
        """
        获取工具列表
        
        Returns:
            工具信息列表
        """
        result = []
        for tool in self.tools:
            # 提取description的第一行非空文本
            desc_lines = [line.strip() for line in tool.description.split('\n') if line.strip()]
            description = desc_lines[0] if desc_lines else tool.name
            
            result.append({
                "name": tool.name,
                "description": description
            })
        
        return result


